package com.hero.take.util;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ListHelpper {
    private static final Logger LOGGER = LoggerFactory.getLogger(ListHelpper.class);

    /**
     * 列表是否可用
     *
     * @param sources
     * @param <T>
     * @return
     */
    public static <T> boolean isValid(List<T> sources) {
        return !(sources == null || sources.isEmpty() || !ListHelpper.exists(sources, x -> x != null));
    }

    /**
     * 添加列表
     *
     * @param sources
     * @param adds
     * @param <T>
     * @return
     */
    public static <T> void listAdd(List<T> sources, List<T>... adds) {
        if (sources == null) return;
        if (adds == null || adds.length == 0) return;
        for (List<T> add : adds) {
            List<T> ts = where(add, x -> x != null);
            if (!isValid(ts)) continue;
            sources.addAll(ts);
        }
    }

    /**
     * 添加列表
     *
     * @param sources
     * @param <T>
     * @return
     */
    public static <T> void listAdd(List<T> sources, T t) {
        if (sources == null) return;
        if (t == null) return;
        sources.add(t);
    }

    /**
     * 添加列表
     *
     * @param sources
     * @param adds
     * @param <T>
     * @return
     */
    public static <T, R> void listAdd(List<T> sources, Function<? super T, ? extends R> keyMap, List<T>... adds) {
        if (sources == null) return;
        if (adds == null || adds.length == 0) return;
        for (List<T> add : adds) {
            List<T> ts = where(add, x -> x != null);
            if (!isValid(ts)) continue;
            if (keyMap == null) {
                sources.addAll(ts);
            } else {
                ts.forEach(z -> {
                    R obj = keyMap.apply(z);
                    if (obj == null) return;
                    T t = ListHelpper.first(sources, y -> obj.equals(keyMap.apply(y)));
                    if (t != null) sources.remove(t);
                    sources.add(z);
                });
            }
        }
    }

    /**
     * 组装一个List
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T> List<T> getList(T... t) {
        List<T> result = new ArrayList<>();
        for (T t1 : t) {
            if (t1 != null) result.add(t1);
        }
        return result;
    }

    /**
     * 组装一个Set
     *
     * @param t
     * @param <T>
     * @return
     */
    public static <T> Set<T> getSet(T... t) {
        Set result = new HashSet();
        for (T t1 : t) {
            if (t1 != null) result.add(t1);
        }
        return result;
    }

    /**
     * 获取某列
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> selectOne(List<T> ts, Function<? super T, ? extends R> mapper) {
        return selectOne(ts, mapper, null);
    }

    /**
     * 获取某列
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> selectOne(List<T> ts, Function<? super T, ? extends R> mapper, R defaultValue) {
        List<R> result = selectOne(ts, mapper, null);
        if (defaultValue != null) {
            if (result == null) result = new ArrayList<>();
            result.add(defaultValue);
        }
        return result;
    }

    /**
     * 获取某列
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> Set<R> setOne(List<T> ts, Function<? super T, ? extends R> mapper) {
        return setOne(ts, mapper, null);
    }

    /**
     * 获取某列
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> selectOne(List<T> ts, Function<? super T, ? extends R> mapper, Predicate<? super T> predicate) {
        return selectOne(ts, mapper, predicate, false);
    }

    /**
     * 获取某列
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> List<R> selectOne(List<T> ts, Function<? super T, ? extends R> mapper, Predicate<? super T> predicate, boolean removeDuplicates) {
        if (ts == null || mapper == null) return null;
        Stream<T> resultStream = predicate != null ? ts.stream().filter(predicate) : ts.stream();
        if (removeDuplicates)
            return resultStream.filter(x -> x != null && mapper.apply(x) != null).map(mapper).distinct().collect(Collectors.toList());
        return resultStream.filter(x -> x != null && mapper.apply(x) != null).map(mapper).collect(Collectors.toList());
    }

    /**
     * 获取某列
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> Set<R> setOne(List<T> ts, Function<? super T, ? extends R> mapper, Predicate<? super T> predicate) {
        if (ts == null || mapper == null) return null;
        Stream<T> resultStream = predicate != null ? ts.stream().filter(predicate) : ts.stream();
        return resultStream.filter(x -> x != null && mapper.apply(x) != null).map(mapper).collect(Collectors.toSet());
    }

    /**
     * 获取某列某值
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> R getListValue(List<T> ts, Function<? super T, ? extends R> mapper) {
        return getListValue(ts, mapper, null, null);
    }

    /**
     * 获取某列某值
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> R getListValue(List<T> ts, Function<? super T, ? extends R> mapper, Predicate<? super T> predicate) {
        return getListValue(ts, mapper, predicate, null);
    }

    /**
     * 获取某列某值
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> R getListValue(List<T> ts, Function<? super T, ? extends R> mapper, Predicate<? super T> predicate, R defaultValue) {
        List<? extends R> list = selectOne(ts, mapper, predicate);
        if (!isValid(list)) return defaultValue;
        return first(list);
    }

    /**
     * 获取某列
     *
     * @param ts
     * @param mapper
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R> Set<R> selectOneBySetList(List<T> ts, Function<? super T, ? extends R> mapper, Predicate<? super T> predicate) {
        if (ts == null || mapper == null) return null;
        Stream<T> resultStream = predicate != null ? ts.stream().filter(predicate) : ts.stream();
        return resultStream.filter(x -> x != null && mapper.apply(x) != null).map(mapper).collect(Collectors.toSet());
    }

    /**
     * 筛选数据
     *
     * @param sources
     * @param predicate
     * @param <T>
     * @return
     */
    public static <T> List<T> where(List<T> sources, Predicate<? super T> predicate) {
        if (sources == null) return null;
        if (predicate == null) return sources;
        return sources.stream().filter(predicate).collect(Collectors.toList());
    }

    public static <T> long count(List<T> sources) {
        return count(sources, null);
    }

    public static <T> long count(List<T> sources, Predicate<? super T> predicate) {
        if (sources == null) return 0;
        if (predicate == null) return sources.size();
        return sources.stream().filter(predicate).count();
    }

    public static <T> boolean exists(List<T> sources, Predicate<? super T> predicate) {
        if (sources == null) return false;
        if (predicate == null) return true;
        return sources.stream().filter(predicate).count() > 0;
    }

//    /**
//     * 筛选数据
//     *
//     * @param sources
//     * @param <T>
//     * @return
//     */
//    public static <T> T second(List<T> sources) {
//        if (ListHelpper.count(sources) == 2) return sources.get(1);
//        return null;
//    }

    /**
     * 筛选数据
     *
     * @param sources
     * @param <T>
     * @return
     */
    public static <T> T first(List<T> sources) {
        return first(sources, null);
    }

    /**
     * 筛选数据
     *
     * @param sources
     * @param predicate
     * @param <T>
     * @return
     */
    public static <T> T first(List<T> sources, Predicate<? super T> predicate) {
        return first(sources, predicate, null);
    }

    /**
     * 筛选数据
     *
     * @param sources
     * @param predicate
     * @param <T>
     * @return
     */
    public static <T> T first(List<T> sources, Predicate<? super T> predicate, T defaultValue) {
        if (!isValid(sources)) return defaultValue;
        if (predicate == null) return sources.get(0);
        List<T> result = sources.stream().filter(predicate).collect(Collectors.toList());
        if (!isValid(result)) return defaultValue;
        return result.get(0);
    }

    public static <T> List<T> listList2List(List<List<T>> sources) {
        if (!ListHelpper.isValid(sources)) return null;
        List<T> result = new ArrayList<>();
        sources.forEach(x -> ListHelpper.listAdd(result, x));
        return result;
    }

    /**
     * 分割
     *
     * @param list
     * @param len
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> splitList(List<T> list, int len) {
        if (list == null || list.size() == 0 || len < 1) {
            return null;
        }

        List<List<T>> result = new ArrayList<List<T>>();


        int size = list.size();
        int count = (size + len - 1) / len;


        for (int i = 0; i < count; i++) {
            List<T> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }

    /**
     * 分组
     *
     * @param list
     * @param len  分几组
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> groupList(List<T> list, int len) {
        if (!isValid(list)) {
            return null;
        }
        List<List<T>> result = new ArrayList<List<T>>();

        int size = list.size();
        int oneGroupNum = size / len;
        int lastNum = size % len;//剩余数量
        if (oneGroupNum == 0) {
            list.forEach(x -> result.add(ListHelpper.getList(x)));
            return result;
        }
        int add = 0;
        for (int i = 0; i < len; i++) {
            int start = i * oneGroupNum + add;
            int end = (i + 1) * oneGroupNum + add;
            if (lastNum > 0) {
                end++;
                add++;
                lastNum--;
            }
            if (i == len - 1) end = size;
            List<T> subList = list.subList(start, end);
            result.add(subList);
        }
        return result;
    }

    /**
     * 均分
     *
     * @param list
     * @param n
     * @param <T>
     * @return
     */
    public static <T> List<List<T>> averageAssign(List<T> list, int n) {
        List<List<T>> result = new ArrayList<List<T>>();
        int remaider = list.size() % n;  //(先计算出余数)
        int number = list.size() / n;  //然后是商
        int offset = 0;//偏移量
        for (int i = 0; i < n; i++) {
            List<T> value = null;
            if (remaider > 0) {
                value = list.subList(i * number + offset, (i + 1) * number + offset + 1);
                remaider--;
                offset++;
            } else {
                value = list.subList(i * number + offset, (i + 1) * number + offset);
            }
            result.add(value);
        }
        return result;
    }

    /**
     * 去重
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T> List<T> removeDuplicates(List<T> list) {
        if (list == null) return null;
        return list.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 去重
     *
     * @param list
     * @param <T>
     * @return
     */
    public static <T, R> List<T> removeDuplicates(List<T> list, Function<? super T, ? extends R> function) {
        if (!ListHelpper.isValid(list)) return list;
        Map<? extends R, List<T>> groupData = groupBy(list, function);
        List<T> result = new ArrayList<>();
        MapHelpper.forEach(groupData, (k, v) -> result.add(first(v)));
        return result;
    }

    /**
     * 获取最大值
     *
     * @param sources
     * @param function
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R extends Comparable<? super R>> R getMax(List<T> sources, Function<? super T, ? extends R> function) {
        return getMax(sources, function, null);
    }

    /**
     * 获取最大值
     *
     * @param sources
     * @param function
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R extends Comparable<? super R>> R getMax(List<T> sources, Function<? super T, ? extends R> function, R defaultValue) {
        sources = where(sources, x -> function.apply(x) != null);
        if (!ListHelpper.isValid(sources)) return defaultValue;
        Optional<T> max = sources.stream().max(Comparator.comparing(x -> function.apply(x)));
        return max.isPresent() ? function.apply(max.get()) : defaultValue;
    }

    /**
     * 获取最大值
     *
     * @param sources
     * @param function
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R extends Comparable<? super R>> R getMin(List<T> sources, Function<? super T, ? extends R> function) {
        return getMin(sources, function, null);
    }

    /**
     * 获取最大值
     *
     * @param sources
     * @param function
     * @param <T>
     * @param <R>
     * @return
     */
    public static <T, R extends Comparable<? super R>> R getMin(List<T> sources, Function<? super T, ? extends R> function, R defaultValue) {
        sources = where(sources, x -> function.apply(x) != null);
        if (!ListHelpper.isValid(sources)) return defaultValue;
        Optional<T> max = sources.stream().min(Comparator.comparing(x -> function.apply(x)));
        return max.isPresent() ? function.apply(max.get()) : defaultValue;
    }

    /**
     * 字符串转数组
     *
     * @param s
     * @return
     */
    public final static List<Integer> strToIntList(String s) {
        return CommonConvert.convert(strToList(s, ","), x -> NumberHelpper.isInteger(x) ? Integer.valueOf(x) : null);
    }

    /**
     * 字符串转数组
     *
     * @param s
     * @return
     */
    public final static List<Integer> strToIntList(String s, String p) {
        return CommonConvert.convert(strToList(s, p), x -> NumberHelpper.isInteger(x) ? Integer.valueOf(x) : null);
    }

    /**
     * 字符串转数组
     *
     * @param s
     * @return
     */
    public final static List<Short> strToShortList(String s) {
        return CommonConvert.convert(strToList(s, ","), x -> NumberHelpper.isInteger(x) ? Short.valueOf(x) : null);
    }

    /**
     * 字符串转数组
     *
     * @param s
     * @return
     */
    public final static List<String> strToList(String s) {
        return strToList(s, ",");
    }

    /**
     * 字符串转数组
     *
     * @param s
     * @param p
     * @return
     */
    public final static List<String> strToList(String s, String p) {
        if (StringUtils.isBlank(s)) return new ArrayList<>();
        if (StringUtils.isBlank(p)) p = ",";
        //* ^ : | . \
        if ("|".equals(p)) p = "\\|";
        if ("*".equals(p)) p = "\\*";
        if (":".equals(p)) p = "\\:";
        if (".".equals(p)) p = "\\.";
        if ("/".equals(p)) p = "\\/";
        if ("\\".equals(p)) p = "\\\\";
        return getList(s.split(p));
    }

    /**
     * list合并
     *
     * @param ts
     * @param <T>
     * @return
     */
    public final static <T> List<T> listMerge(List<T>... ts) {
        ArrayList<T> result = new ArrayList<>();
        if (ts == null || ts.length == 0) return result;
        for (List<T> t : ts) {
            t = ListHelpper.where(t, x -> x != null);
            if (!ListHelpper.isValid(t)) continue;
            result.addAll(t);
        }
        return result;
    }

    /**
     * list交集
     *
     * @param ts
     * @param <T>
     * @return
     */
    public final static <T> List<T> listRetain(List<T>... ts) {
        if (ts == null || ts.length == 0) return null;
        List<T> result = null;
        for (List<T> t : ts) {
            if (t == null) continue;
            if (result == null) {
                result = t;
                continue;
            }
            t = ListHelpper.where(t, x -> x != null);
            if (!ListHelpper.isValid(t)) return t;
            result.retainAll(t);
        }
        return result;
    }

    /**
    public final static <T, R> String list2Str(List<T> sources, Function<? super T, ? extends R> mapper) {
        return list2Str(sources, mapper, ",");
    }
     */

    /**
    public final static <T, R> String list2Str(List<T> sources, Function<? super T, ? extends R> mapper, boolean removeDuplicates) {
        return list2Str(sources, mapper, ",", removeDuplicates);
    }

    public final static <T, R> String list2Str(List<T> sources, Function<? super T, ? extends R> mapper, String separator) {
        return list2Str(sources, mapper, separator, false);
    }
     */

    /**
    public final static <T, R> String list2Str(List<T> sources, Function<? super T, ? extends R> mapper, String separator, boolean removeDuplicates) {
        if (StringUtils.isBlank(separator)) separator = ",";
        if (!isValid(sources)) return "";
        List<? extends R> list = removeDuplicates ? removeDuplicates(selectOne(sources, mapper)) : selectOne(sources, mapper);
        return StringUtils.join(list, separator);
    }
     */

    public final static void list2KeyValue(List<String> listStr, String split, List<String> keys, List<String> values) {
        ListHelpper.forEach(listStr, x -> {
            if (StringUtils.isBlank(x)) return;
            x = x.replace("，", ",");
            List<String> list = ListHelpper.strToList(x, split);
            if (!ListHelpper.isValid(list) || list.size() != 2) return;
            String v1 = list.get(0);
            String v2 = list.get(1);
            if (!keys.contains(v1)) keys.add(list.get(0));
            if (!values.contains(v2)) values.add(list.get(1));
        });
    }

    public final static <T> List<T> order(List<T> sources, Comparator<? super T> comparator, boolean desc) {
        if (!isValid(sources) || comparator == null) return sources;
        return sources.stream().sorted(desc ? comparator.reversed() : comparator).collect(Collectors.toList());
    }

    public final static <T> List<T> order(List<T> sources, Comparator<? super T> comparator) {
        return order(sources, comparator, false);
    }

    public final static <T, U extends Comparable<? super U>> List<T> order(List<T> sources, Function<? super T, ? extends U> keyExtractor, boolean desc) {
        return order(sources, Comparator.comparing(keyExtractor), desc);
    }

    public final static <T, U extends Comparable<? super U>> List<T> order(List<T> sources, Function<? super T, ? extends U> keyExtractor) {
        return order(sources, Comparator.comparing(keyExtractor));
    }

    public final static <T, U extends Comparable<? super U>> T max(List<T> sources, Function<? super T, ? extends U> keyExtractor) {
        return max(sources, keyExtractor, null);
    }

    public final static <T, U extends Comparable<? super U>> T max(List<T> sources, Function<? super T, ? extends U> keyExtractor, Predicate<? super T> predicate) {
        sources = where(sources, predicate);
        sources = where(sources, x -> keyExtractor.apply(x) != null);
        if (!isValid(sources) || keyExtractor == null) return null;
//        Stream<T> stream = predicate == null ? sources.stream() : sources.stream().filter(predicate);
        Optional<T> data = sources.stream().max(Comparator.comparing(keyExtractor));
        return data.isPresent() ? data.get() : null;
    }

    public final static <T, U extends Comparable<? super U>> T min(List<T> sources, Function<? super T, ? extends U> keyExtractor) {
        return min(sources, keyExtractor, null);
    }

    public final static <T, U extends Comparable<? super U>> T min(List<T> sources, Function<? super T, ? extends U> keyExtractor, Predicate<? super T> predicate) {
        sources = where(sources, predicate);
        sources = where(sources, x -> keyExtractor.apply(x) != null);
        if (!isValid(sources) || keyExtractor == null) return null;
//        Stream<T> stream = predicate == null ? sources.stream() : sources.stream().filter(predicate);
        Optional<T> data = sources.stream().min(Comparator.comparing(keyExtractor));
        return data.isPresent() ? data.get() : null;
    }

    public final static <T, K> Map<? extends K, List<T>> groupBy(List<T> sources, Function<? super T, ? extends K> group) {
        if (!isValid(sources) || group == null) return null;
        return sources.stream().collect(Collectors.groupingBy(group));
    }

    public final static <T, K> List<T> groupByGetTop1(List<T> sources, Function<? super T, ? extends K> group) {
        Map<? extends K, List<T>> groupData = groupBy(sources, group);
        if (groupData == null) return null;
        List<T> result = new ArrayList<>();
        MapHelpper.forEach(groupData, (k, v) -> result.add(ListHelpper.first(v)));
        return result;
    }

    public final static <T> int sumInt(List<T> sources, ToIntFunction<? super T> mapper) {
        if (!isValid(sources) || mapper == null) return 0;
        return sources.stream().mapToInt(mapper).sum();
    }

    public final static <T> int sumInt(List<T> sources, ToIntFunction<? super T> mapper, Predicate<? super T> predicate) {
        if (!isValid(sources) || mapper == null) return 0;
        if (predicate != null) {
            return sources.stream().filter(predicate).mapToInt(mapper).sum();
        }
        return sources.stream().mapToInt(mapper).sum();
    }

    public final static <T> float sumFloat(List<T> sources, ToDoubleFunction<? super T> mapper) {
        if (!isValid(sources) || mapper == null) return 0;
        return sumFloat(sources, mapper, null);
    }

    public final static <T> float sumFloat(List<T> sources, ToDoubleFunction<? super T> mapper, Predicate<? super T> predicate) {
        if (!isValid(sources) || mapper == null) return 0;
        if (predicate != null) {
            return (float) sources.stream().filter(predicate).mapToDouble(mapper).sum();
        }
        return (float) sources.stream().mapToDouble(mapper).sum();
    }
    public final static <T> Double sumDouble(List<T> sources, ToDoubleFunction<? super T> mapper) {
        if (!isValid(sources) || mapper == null) return 0.00;
        return sources.stream().mapToDouble(mapper).sum();
    }

    public final static <T> BigDecimal sumBigDecimal(List<T> sources, Function<? super T, ? extends BigDecimal> mapper) {
        return sumBigDecimal(sources, mapper, null);
    }

    public final static <T> BigDecimal sumBigDecimal(List<T> sources, Function<? super T, ? extends BigDecimal> mapper, Predicate<? super T> predicate) {
        List<BigDecimal> values = ListHelpper.selectOne(sources, mapper, predicate);
        if (!isValid(values) || mapper == null) return BigDecimal.ZERO;
        BigDecimal r = BigDecimal.ZERO;
        for (BigDecimal v : values) {
            if (v == null) continue;
            r = r.add(v);
        }
        return NumberHelpper.decimal2(r);
    }

    public final static <T> long sumLong(List<T> sources, ToLongFunction<? super T> mapper, Predicate<? super T> predicate) {
        if (!isValid(sources) || mapper == null) return 0;
        if (predicate != null) {
            return sources.stream().filter(predicate).mapToLong(mapper).sum();
        }
        return sources.stream().mapToLong(mapper).sum();
    }

    /**
     * 读取最底层的叶子节点
     *
     * @param result
     * @param sources
     * @param curr
     * @param idMap
     * @param parentMap
     * @param <T>
     * @param <R>
     */
    public final static <T, R> void getBottom(List<T> result, List<T> sources, T curr, Function<? super T, ? extends R> idMap, Function<? super T, ? extends R> parentMap) {
        if (result == null) return;
        List<T> childs = ListHelpper.where(sources, x -> parentMap.apply(x).equals(idMap.apply(curr)));
        if (!ListHelpper.isValid(childs)) {
            result.add(curr);
            return;
        }
        childs.forEach(child -> {
            getBottom(result, sources, child, idMap, parentMap);
        });
    }

    /**
     * 读取上级
     *
     * @param sources
     * @param id
     * @param idMap
     * @param parentMap
     * @param <T>
     * @param <R>
     * @return
     */
    public final static <T, R> List<T> getParents(List<T> sources, R id, Function<? super T, ? extends R> idMap, Function<? super T, ? extends R> parentMap) {
        T curr = first(sources, x -> idMap.apply(x).equals(id));
        if (curr == null) return null;
        List<T> parents = new ArrayList<>();
        getParents(sources, curr, parents, idMap, parentMap);
        return parents;
    }

    /**
     * 读取上级
     *
     * @param sources
     * @param curr
     * @param result
     * @param idMap
     * @param parentMap
     * @param <T>
     * @param <R>
     */
    static <T, R> void getParents(List<T> sources, T curr, List<T> result, Function<? super T, ? extends R> idMap, Function<? super T, ? extends R> parentMap) {
        T parent = first(sources, x -> idMap.apply(x).equals(parentMap.apply(curr)));
        if (parent == null) return;
        result.add(parent);
        getParents(sources, parent, result, idMap, parentMap);
    }

    /**
    public final static <T, R> List<T> getChilds(List<T> sources, R pid, Function<? super T, ? extends R> idMap, Function<? super T, ? extends R> parentMap, boolean flagChilds) {
        return getChilds(sources, pid, idMap, parentMap, flagChilds, true);
    }
     */

    /**
     * 获取子类
     *
     * @param sources
     * @param pid
     * @param idMap
     * @param parentMap
     * @param flagChilds    是否树形结构
     * @param includeParent 是否包含当前
     * @param <T>
     * @param <R>
     * @return
     */
    /**
    public final static <T, R> List<T> getChilds(List<T> sources, R pid, Function<? super T, ? extends R> idMap, Function<? super T, ? extends R> parentMap, boolean flagChilds, boolean includeParent) {
        if (!ListHelpper.isValid(sources)) return null;
        //(StringUtils.equals(ObjectHelpper.Obj2Str(pid), "0") && parentMap.apply(x).equals(0))
        List<T> parents = null;
        if (StringUtils.equals(ObjectHelpper.Obj2Str(pid), "0")) {
            parents = ListHelpper.where(sources, x -> parentMap.apply(x).equals(0));
        } else {
            parents = ListHelpper.where(sources, x -> idMap.apply(x).equals(pid));
        }
        if (!ListHelpper.isValid(parents)) parents = ListHelpper.where(sources, x -> parentMap.apply(x).equals(pid));
        if (!ListHelpper.isValid(parents)) return null;
        List<T> result = new ArrayList<>();
        parents.forEach(parent -> {
            if (includeParent) result.add(parent);
            getChilds(sources, parent, result, idMap.apply(parent), idMap, parentMap, flagChilds);
        });
        return result;
    }

    public final static <T, R> List<T> getChilds(List<T> sources, R pid, Function<? super T, ? extends R> idMap, Function<? super T, ? extends R> parentMap) {
        return getChilds(sources, pid, idMap, parentMap, false);
    }

    static <T, R> void getChilds(List<T> sources, T parent, List<T> result, R pid, Function<? super T, ? extends R> idMap, Function<? super T, ? extends R> parentMap, boolean flagChilds) {
        List<T> childs = ListHelpper.where(sources, x -> parentMap.apply(x).equals(pid));
        if (!ListHelpper.isValid(childs)) return;
        if (flagChilds && parent instanceof TreeSetChilds) {
            ((TreeSetChilds) parent).setChildren(childs);
        } else {
            result.addAll(childs);
        }
        childs.forEach(child -> {
            R id = idMap.apply(child);
            getChilds(sources, child, result, id, idMap, parentMap, flagChilds);
        });
    }
     */

    /**
     * 获取指定的上级和下级数据
     *
     * @param sources
     * @param idMap
     * @param parentMap
     * @param ids
     * @param <T>
     * @param <R>
     * @return
     */
    /**
    public final static <T, R> List<T> getChildAndParent(List<T> sources, Function<? super T, ? extends R> idMap, Function<? super T, ? extends R> parentMap, List<R> ids) {
        List<R> result = new ArrayList<>();
        forEach(ids, x -> {
            List<T> parents = getParents(sources, x, idMap, parentMap);
            List<T> children = getChilds(sources, x, idMap, parentMap);
            ListHelpper.listAdd(result, ListHelpper.selectOne(parents, idMap));
            ListHelpper.listAdd(result, ListHelpper.selectOne(children, idMap));
            result.add(x);
        });
        return where(sources, x -> result.contains(idMap.apply(x)));
    }
*/

    /**
     * 找出A有B没有
     *
     * @param dataA
     * @param dataB
     * @param <T>
     * @return
     */
    public final static <T> List<T> getAHadAndBNotHad(List<T> dataA, List<T> dataB) {
        if (!ListHelpper.isValid(dataA)) return null;
        if (!ListHelpper.isValid(dataB)) return dataA;
        List<T> result = new ArrayList<>();
        dataA.forEach(a -> {
            T b = ListHelpper.first(dataB, x -> x.equals(a));
            if (b == null)
                result.add(a);
        });
        return result;
    }

    /**
     * 找出A有B没有
     *
     * @param dataA
     * @param dataB
     * @param <T>
     * @return
     */
    /**
    public final static <T, R> List<T> getAHadAndBNotHad(List<T> dataA, List<T> dataB, Function<? super T, ? extends R>... key) {
        if (!ListHelpper.isValid(dataA) || key == null) return null;
        if (!ListHelpper.isValid(dataB)) return dataA;
        List<T> result = new ArrayList<>();
        dataA.forEach(a -> {
//            T b = ListHelpper.first(dataB, x -> key.apply(a).equals(key.apply(x)));
            T b = ListHelpper.first(dataB, x -> getPredicate(a, x, key));
            if (b == null)
                result.add(a);
        });
        return result;
    }
     */

    public interface GetData<T> {
        List<T> getModels();
    }

    public interface GetModel<T> {
        T get();
    }

    /**
     * 从B中设置A的值
     *
     * @param dataA
     * @param dataB
     * @param predicate 匹配两组数据的条件
     * @param map       从B获取数据的方法
     * @param func      //设置A的方法
     * @param <T>
     * @param <PT>
     * @param <VT>
     */
    /**
    public final static <T, PT, VT> void setAfromB(List<T> dataA, List<T> dataB, Function<? super T, ? extends PT> predicate, Function<? super T, ? extends VT> map, SetModel<T, VT> func) {
        setAfromB(dataA, dataB, predicate, map, func, null);
    }
     */

    /**
     * 从B中设置A的值
     *
     * @param dataA
     * @param dataB
     * @param predicate    匹配两组数据的条件
     * @param map          从B获取数据的方法
     * @param func         设置A的方法
     * @param defaultValue 找不到时候设置的默认值
     * @param <T>
     * @param <PT>
     * @param <VT>
     */
    /**
    public final static <T, PT, VT> void setAfromB(List<T> dataA, List<T> dataB, Function<? super T, ? extends PT> predicate, Function<? super T, ? extends VT> map, SetModel<T, VT> func, VT defaultValue) {
        if (!ListHelpper.isValid(dataA) || predicate == null) return;
        if (!ListHelpper.isValid(dataB)) return;
        dataA.forEach(a -> {
            T b = ListHelpper.first(dataB, x -> predicate.apply(a).equals(predicate.apply(x)));
            if (b != null) {
                try {
                    func.setModel(a, map.apply(b));
                } catch (BusinessException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            } else if (defaultValue != null) {
                try {
                    func.setModel(a, defaultValue);
                } catch (BusinessException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        });
    }
     */

    /**
     * 从B中设置A的值
     *
     * @param dataA
     * @param dataB
     * @param predicate    匹配两组数据的条件
     * @param func         设置A的方法
     * @param defaultValue 找不到时候设置的默认值
     * @param <T>
     * @param <PT>
     */
    /**
    public final static <T, PT> void setAfromB(List<T> dataA, List<T> dataB, Function<? super T, ? extends PT> predicate, SetModel<T, T> func, T defaultValue) {
        if (!ListHelpper.isValid(dataA) || predicate == null) return;
        if (!ListHelpper.isValid(dataB)) return;
        dataA.forEach(a -> {
            T b = ListHelpper.first(dataB, x -> predicate.apply(a).equals(predicate.apply(x)));
            if (b != null) {
                try {
                    func.setModel(a, b);
                } catch (BusinessException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            } else if (defaultValue != null) {
                try {
                    func.setModel(a, defaultValue);
                } catch (BusinessException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        });
    }
     */

    /**
     * 从B中设置A的值
     *
     * @param dataA
     * @param dataB
     * @param predicate    匹配两组数据的条件
     * @param func         设置A的方法
     * @param defaultValue 找不到时候设置的默认值
     * @param <T>
     * @param <PT>
     */
    /**
    public final static <T, PT> void setAfromB(List<T> dataA, List<T> dataB, SetModel<T, T> func, T defaultValue, Function<? super T, ? extends PT>... predicate) {
        if (!ListHelpper.isValid(dataA) || predicate == null) return;
        if (!ListHelpper.isValid(dataB)) return;
        dataA.forEach(a -> {
            T b = ListHelpper.first(dataB, x -> getPredicate(a, x, predicate));
            if (b != null) {
                try {
                    func.setModel(a, b);
                } catch (BusinessException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            } else if (defaultValue != null) {
                try {
                    func.setModel(a, defaultValue);
                } catch (BusinessException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
        });
    }
     */

    public final static <T> void forEach(List<T> sources, Consumer<? super T> action) {
        forEach(sources, action, null);
    }

    public final static <T> void forEach(List<T> sources, Consumer<? super T> action, Predicate<? super T> predicate) {
        sources = where(sources, predicate);
        if (!isValid(sources)) return;
        sources.forEach(action);
    }

    public final static List<Integer> ints2List(Predicate<Integer> predicate, int... ints) {
        if (ints == null || ints.length == 0) return null;
        List<Integer> result = new ArrayList<>();
        for (int anInt : ints) {
            if (predicate == null || predicate.test(anInt)) result.add(anInt);
        }
        return result;
    }

    public final static <T> boolean contains(List<T> list, T contain) {
        if (!ListHelpper.isValid(list)) return false;
        return list.contains(contain);
    }

    public final static <T> T getIndex(List<T> list, int index) {
        if (!ListHelpper.isValid(list)) return null;
        if (index >= list.size()) return null;
        return list.get(index);
    }
}